#ifndef __NETWORK_H__
#define __NETWORK_H__

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "list.h"
#include "lock.h"
#include "wait.h"
#include "log.h"

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <fcntl.h>

#define MAX_NET_MSG_LENGTH		1400
#define MAX_TCP_CLIENT		    8

struct net_msg {
	uint8_t buffer[MAX_NET_MSG_LENGTH];
	uint32_t length;
};

enum NETWORK_TYPE
{
    NETWORK_TYPE_UDP = 0,
    NETWORK_TYPE_TCP,
    NETWORK_TYPE_MAX,
};

struct tcp_client {
    struct list_head head;
    int id;
    int socket;
    pthread_t task_pid;
    struct sockaddr_in s_in;
    void *ptr;
};

struct network;

enum NETWORK_EVENT
{
    NETWORK_EVENT_NONE = 0,
    NETWORK_EVENT_TEST,
    NETWORK_EVENT_MAX,
};

typedef int32_t (*network_event_notify)(struct network*, int32_t, void*, void*);

struct network_event_action
{
    network_event_notify notify;
    void* object;
    struct network_event_action* next;
};

struct network_operation
{
    int32_t (*init)(struct network*);
    int32_t (*release)(struct network*);

    int32_t (*udp_setup)(struct network*, uint16_t);
    int32_t (*tcp_setup)(struct network*, uint16_t);
    int32_t (*close)(struct network*);

    int32_t (*write)(struct network*, struct tcp_client*, uint8_t *, uint32_t);

    int32_t (*put_client)(struct network*, struct list_head*, struct tcp_client*);
    struct tcp_client* (*get_client)(struct network*, struct list_head*);

    int32_t (*register_notify)(struct network*, int32_t, network_event_notify notify, void*);
    int32_t (*unregister_notify)(struct network*, int32_t, void*);
    int32_t (*trigger_notify)(struct network*, int32_t, void*);
};

struct network
{
    struct list_head head;
    wait_t wait;
    lock_t lock;
    lock_t notify_lock;

    int running_flag;
    pthread_t pid;

    int opened;

    int type;

    int sock_fd;
    uint32_t port;
	struct sockaddr_in s_addr;
    struct net_msg rx_buffer;

    int client_nums;
    struct tcp_client tcp_client[MAX_TCP_CLIENT];
    struct list_head free_client_queue;
    struct list_head used_client_queue;

    struct network_operation* op;
    struct network_event_action *paction[NETWORK_EVENT_MAX];
};

int32_t create_init_network(struct network** pnetwork);
void release_destroy_network(struct network* pnetwork);
        
#endif
